<template>
  <KView class="system-index">
    <KView class="system-index-content" :class="{'has-full':!hasFooter}">
      <template v-if="isShow">
        <slot v-if="isMiniprogram"></slot>
        <router-view v-else />
      </template>
    </KView>
    <KView v-if="hasFooter">
      <sys-footer @item-click="itemClick"></sys-footer>
    </KView>

    <sys-dialog v-if="isMiniprogram" is-center is-middle :visible.sync="openAuth" :width="600" :height="540" animation-name="bottom">
      <template slot-scope="scope">
        <auth-dialog v-if="scope.isShow" @auth-success="authSuccess" @close="authClose"></auth-dialog>
      </template>
    </sys-dialog>
  </KView>
</template>

<script>
  import SysDialog from 'common/sysDialog';
  import SysFooter from './footer';
  import AuthDialog from './authDialog';

  import GlobalData from 'utils/globalData';
  import SystemUtil from 'utils/systemUtil';
  import MapUtil from 'utils/mapUtil';

  import MinAuthApi from 'services/minAuthApi';
  import CommonApi from 'services/commonApi';

  import storeMixins from 'mixins/storeMixins';

  export default {
    mixins: [storeMixins],

    props: {
      hasLogin: {
        type: Boolean,
        default: true
      }
    },

    computed: {
      hasFooter() {
        let online = this.online;
        if (!online) {
          return false;
        }

        let name = this.$route.name;
        let hideTabBarRoutes = GlobalData.hideTabBarRoutes;
        return hideTabBarRoutes.indexOf(name) === -1;
      }
    },

    data() {
      return {
        isShow: false,
        timeout: null,
        isMiniprogram: process.env.isMiniprogram,
        online: false,
        openAuth: false,
        isDestroy: false
      };
    },

    created() {
      window.resetTokenRunning = () => {
        this.toRefreshTokenRunning();
      };

      if (!this.isMiniprogram) {
        this.toLogin();
        this.online = true;
        return;
      }

      let pages = getCurrentPages();
      if (pages.length > 1) {
        this.toLogin();
        this.online = true;
        return;
      }
      wx.onNetworkStatusChange(res => {
        if (!res.isConnected) {
          SystemUtil.alert('网络未连接', '提示');
          return;
        }

        if (this.isShow) {
          return;
        }

        this.toLogin();
        this.online = true;
      });

      wx.getNetworkType({
        success: res => {
          if (res.networkType === 'none') {
            SystemUtil.alert('网络未连接', '提示');
            return;
          }
          this.toLogin();
          this.online = true;
        }
      });
    },

    beforeDestroy() {
      this.clearTimeout();
      if (this.isMiniprogram) {
        wx.offNetworkStatusChange();
      }
      this.isDestroy = true;
    },

    methods: {
      toLogin() {
        if (this.user !== null) {
          this.initData();
          return;
        }

        if (!this.hasLogin && this.defaultUser) {
          this.initData(false);
          return;
        }

        if (!this.isMiniprogram) {
          let jumpUrl = 'https://www.manlitech.com/authPage?url=' + this.$route.path;
          let url = `${GlobalData.wechatAuthUrl}?redirectUrl=${encodeURIComponent(jumpUrl)}`;
          window.location.href = url;
          return;
        }

        this.$api.getSetting({
          success: res => {
            if (!res.authSetting['scope.userInfo']) {
              this.openAuth = true;
              return;
            }
            this.setSysUserData();
          }
        });
      },

      authSuccess() {
        this.openAuth = false;
        this.initData();
      },

      authClose() {
        this.openAuth = false;
        if (this.hasLogin) {
          if (this.isMiniprogram) {
            this.$emit('to-main-page');
          }
          return;
        }

        SystemUtil.showLoading('');
        this.initData(false).then(() => {
          SystemUtil.hideLoading();
        });
      },

      initData(hasRunning = true) {
        let location = this.location;
        if (location !== null) {
          this.isShow = true;
          if (hasRunning) {
            this.toRefreshTokenRunning();
          }
          return window.Promise.resolve(true);
        }

        let user = this.user;
        if (user === null) {
          user = this.defaultUser;
        }
        SystemUtil.showLoading('');
        return MapUtil.getLocationData(user).then(locationData => {
          this.setLocation(locationData);
          this.isShow = true;
          if (hasRunning) {
            this.toRefreshTokenRunning();
          }
          SystemUtil.hideLoading();
          return true;
        }).catch(() => {
          SystemUtil.hideLoading();
          return false;
        });
      },

      setSysUserData() {
        SystemUtil.showLoading('');
        this.$api.login({
          success: res => {
            let code = res.code;
            this.$api.getUserInfo({
              lang: 'zh_CN',
              withCredentials: true,
              success: res => {
                MinAuthApi.authLogin({
                  code: code,
                  encryptedData: res.encryptedData,
                  iv: res.iv
                }).then(res => {
                  SystemUtil.hideLoading();
                  let user = res.user;
                  if (SystemUtil.isEmpty(user.phoneNum)) {
                    user.phoneNum = '';
                  }
                  this.setUser(user);
                  this.setDefaultUser(null);
                  this.setAuthToken(res.authToken);
                  this.setRefreshToken({
                    data: res.refreshToken,
                    time: this.$moment().valueOf()
                  });
                  return this.initData();
                }).catch(() => {
                  SystemUtil.hideLoading();
                });
              },
              fail: error => {
                SystemUtil.hideLoading();
              }
            });
          },
          fail: error => {
            SystemUtil.hideLoading();
          }
        });
      },

      toRefreshTokenRunning() {
        if (this.isMiniprogram) {
          let pages = getCurrentPages();
          if (pages.length > 1) {
            let win = pages[0].window;
            if (win !== window) {
              win.resetTokenRunning();
              return;
            }
          }
        }

        if (!this.hasLogin) {
          if (this.user === null) {
            return;
          }
        }

        this.clearTimeout();
        this.toRefreshToken();
      },

      toRefreshToken() {
        let delayTime;
        let obj = this.refreshToken;
        if (obj === null) {
          delayTime = 25 * 60 * 1000;
        } else {
          let tokenTime = obj.time;
          let nowTime = this.$moment().valueOf();
          if (tokenTime >= nowTime) {
            delayTime = 0;
          } else {
            delayTime = 25 * 60 * 1000 - (nowTime - tokenTime);
            if (delayTime < 0) {
              delayTime = 0;
            }
          }
        }

        this.timeout = setTimeout(() => {
          this.resetToken().then(res => {
            if (this.isDestroy) {
              return;
            }
            this.timeout = null;
            this.toRefreshToken();
          });
        }, delayTime);
      },

      resetToken() {
        let refreshToken = this.refreshToken.data;
        return CommonApi.getTocken(refreshToken).then(res => {
          this.setUser(res.user);
          this.setDefaultUser(null);
          this.setAuthToken(res.authToken);
          this.setRefreshToken({
            data: res.refreshToken,
            time: this.$moment().valueOf()
          });
          return res;
        });
      },

      clearTimeout() {
        let timeout = this.timeout;
        if (timeout !== null) {
          clearTimeout(timeout);
          this.timeout = null;
        }
      },

      itemClick(menu) {
        if (this.isMiniprogram) {
          this.$emit('menu-change', menu);
          return;
        }
        this.$router.push({
          path: menu.path
        });
      }
    },

    components: {
      SysDialog,
      SysFooter,
      AuthDialog
    }
  };
</script>

<style lang="scss">
  .system-index {
    height: 100%;
    overflow: auto;
  }

  .system-index-content {
    height: calc(100% - #{formatPx(110)} - env(safe-area-inset-bottom));

    &.has-full {
      height: calc(100% - env(safe-area-inset-bottom));
    }
  }
</style>